package com.ruoyi.collect.utils;

import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.nio.file.Paths;

/**
 * 图片本地化工具类
 *
 * @author ruoyi
 * @date 2025-11-07
 */
@Component
public class ImageLocalizer {

    private static final Logger log = LoggerFactory.getLogger(ImageLocalizer.class);

    private static final int CONNECT_TIMEOUT = 10000;
    private static final int READ_TIMEOUT = 30000;
    private static final String USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36";

    /**
     * 下载远程图片到本地
     *
     * @param imageUrl 远程图片URL
     * @return 本地图片路径
     */
    public String downloadImage(String imageUrl) {
        if (StringUtils.isEmpty(imageUrl)) {
            return null;
        }

        // 如果已经是本地路径，直接返回
        if (isLocalPath(imageUrl)) {
            return imageUrl;
        }

        try {
            log.debug("开始下载图片: {}", imageUrl);

            // 生成本地文件名
            String extension = getFileExtension(imageUrl);
            String fileName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + extension;
            String localPath = RuoYiConfig.getProfile() + "/collect/" + fileName;

            // 确保目录存在
            File file = new File(localPath);
            File parentDir = file.getParentFile();
            if (!parentDir.exists()) {
                parentDir.mkdirs();
            }

            // 下载图片
            boolean success = downloadFile(imageUrl, localPath);
            if (success) {
                // 返回相对路径
                String relativePath = "/profile/collect/" + fileName;
                log.debug("图片下载成功: {} -> {}", imageUrl, relativePath);
                return relativePath;
            } else {
                log.warn("图片下载失败: {}", imageUrl);
                return imageUrl; // 下载失败返回原URL
            }

        } catch (Exception e) {
            log.error("图片下载异常: {}, 错误: {}", imageUrl, e.getMessage());
            return imageUrl; // 异常时返回原URL
        }
    }

    /**
     * 下载文件
     *
     * @param url      远程URL
     * @param savePath 保存路径
     * @return 是否成功
     */
    private boolean downloadFile(String url, String savePath) {
        RequestConfig config = RequestConfig.custom()
                .setConnectTimeout(CONNECT_TIMEOUT)
                .setSocketTimeout(READ_TIMEOUT)
                .setConnectionRequestTimeout(CONNECT_TIMEOUT)
                .build();

        try (CloseableHttpClient httpClient = HttpClients.custom()
                .setDefaultRequestConfig(config)
                .build()) {

            HttpGet httpGet = new HttpGet(url);
            httpGet.setHeader("User-Agent", USER_AGENT);
            httpGet.setHeader("Accept", "image/*,*/*");

            try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
                int statusCode = response.getStatusLine().getStatusCode();
                if (statusCode != 200) {
                    log.warn("下载失败，HTTP状态码: {}", statusCode);
                    return false;
                }

                HttpEntity entity = response.getEntity();
                if (entity == null) {
                    log.warn("响应内容为空");
                    return false;
                }

                // 写入文件
                try (InputStream inputStream = entity.getContent();
                     FileOutputStream outputStream = new FileOutputStream(savePath)) {

                    byte[] buffer = new byte[4096];
                    int bytesRead;
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        outputStream.write(buffer, 0, bytesRead);
                    }
                }

                return true;
            }

        } catch (Exception e) {
            log.error("文件下载异常: {}", e.getMessage());
            return false;
        }
    }

    /**
     * 批量下载图片
     *
     * @param imageUrls 图片URL数组
     * @return 本地路径数组
     */
    public String[] downloadImages(String[] imageUrls) {
        if (imageUrls == null || imageUrls.length == 0) {
            return new String[0];
        }

        String[] localPaths = new String[imageUrls.length];
        for (int i = 0; i < imageUrls.length; i++) {
            localPaths[i] = downloadImage(imageUrls[i]);
        }
        return localPaths;
    }

    /**
     * 判断是否为本地路径
     *
     * @param path 路径
     * @return 是否为本地路径
     */
    private boolean isLocalPath(String path) {
        if (StringUtils.isEmpty(path)) {
            return false;
        }
        return path.startsWith("/profile/") ||
               path.startsWith("profile/") ||
               !path.startsWith("http://") && !path.startsWith("https://");
    }

    /**
     * 获取文件扩展名
     *
     * @param url URL
     * @return 扩展名（包含点号）
     */
    private String getFileExtension(String url) {
        if (StringUtils.isEmpty(url)) {
            return ".jpg";
        }

        // 去除查询参数
        int queryIndex = url.indexOf('?');
        if (queryIndex > 0) {
            url = url.substring(0, queryIndex);
        }

        // 获取扩展名
        int dotIndex = url.lastIndexOf('.');
        if (dotIndex > 0 && dotIndex < url.length() - 1) {
            String extension = url.substring(dotIndex);
            // 验证扩展名
            if (isValidImageExtension(extension)) {
                return extension.toLowerCase();
            }
        }

        return ".jpg"; // 默认扩展名
    }

    /**
     * 验证是否为有效的图片扩展名
     *
     * @param extension 扩展名
     * @return 是否有效
     */
    private boolean isValidImageExtension(String extension) {
        String[] validExtensions = {".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp"};
        String lowerExt = extension.toLowerCase();
        for (String valid : validExtensions) {
            if (valid.equals(lowerExt)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 清理过期图片
     * 删除指定天数前的采集图片
     *
     * @param days 天数
     * @return 删除的文件数量
     */
    public int cleanExpiredImages(int days) {
        try {
            String collectPath = RuoYiConfig.getProfile() + "/collect/";
            File collectDir = new File(collectPath);
            if (!collectDir.exists() || !collectDir.isDirectory()) {
                return 0;
            }

            long expireTime = System.currentTimeMillis() - (days * 24 * 60 * 60 * 1000L);
            return cleanDirectory(collectDir, expireTime);

        } catch (Exception e) {
            log.error("清理过期图片异常: {}", e.getMessage(), e);
            return 0;
        }
    }

    /**
     * 递归清理目录
     *
     * @param directory  目录
     * @param expireTime 过期时间戳
     * @return 删除数量
     */
    private int cleanDirectory(File directory, long expireTime) {
        int count = 0;
        File[] files = directory.listFiles();
        if (files == null) {
            return count;
        }

        for (File file : files) {
            if (file.isDirectory()) {
                count += cleanDirectory(file, expireTime);
                // 如果目录为空，删除目录
                if (file.listFiles() == null || file.listFiles().length == 0) {
                    file.delete();
                }
            } else {
                // 检查文件修改时间
                if (file.lastModified() < expireTime) {
                    if (file.delete()) {
                        count++;
                        log.debug("删除过期图片: {}", file.getName());
                    }
                }
            }
        }
        return count;
    }
}